6256. Inversion Count

 

Let A[0...n – 1] be an array of n distinct positive integers. If i < j and A[i] > A[j] then the pair (i, j) is called an inversion of A. Given n and an array A your task is to find the number of inversions of A.

 

Input. The first line contains t, the number of testcases followed by a blank space. Each of the t tests start with a number n (n ≤ 200000). Then n + 1 lines follow. In the ith line a number A[i – 1] is given (A[i – 1] ≤ 107). The (n + 1)th line is a blank space.

 

Output. For every test output one line giving the number of inversions of A.

 

Sample Input

Sample Output

2

 

3

3

1

2

 

5

2

3

8

6

1

2

5

 

 

РЕШЕНИЕ

сортировка

 

Анализ алгоритма

При помощи сортировки слиянием вычисляем количество инверсий за O(n logn).

 

Реализация алгоритма

 

#include <cstdio>

#include <cstring>

#include <vector>

#define MAX 200010

using namespace std;

 

int m[MAX];

int tests, n, i, j;

long long swaps;

 

void merge(int *a, int bleft, int bright, int cleft, int cright)

{

  // a[bleft..bright] -> res[]

  // res[0..len-1] a[cleft..cright] are merged into a[bleft..cright]

  // we copy only half of array

  int i, len = bright - bleft + 1, resCur = 0;

  int *res = new int[len];

  memcpy(res,a + bleft,len*sizeof(int));

  while((resCur < len) && (cleft <= cright))

  {

    if (res[resCur] <= a[cleft]) a[bleft++] = res[resCur++];

    else a[bleft++] = a[cleft++], swaps += len - resCur;

  }

  while (resCur < len) a[bleft++] = res[resCur++];

  delete[] res;

}

 

void mergeSort(int *a, int left, int right)

{ 

  if (left >= right) return;

  int middle = (left + right) / 2;

  mergeSort(a,left,middle);

  mergeSort(a,middle+1,right);

  merge(a, left, middle, middle + 1, right);

}

 

int main(void)

{

  scanf("%d",&tests);

  while(tests--)

  {

    scanf("%d",&n);

    for(swaps = i = 0; i < n; i++) scanf("%d",&m[i]);

    mergeSort(m, 0, n - 1);

    printf("%lld\n",swaps);

  }

  return 0;

}